#include <VPixelCommon.h>


sampler2D DiffuseTex;
sampler2D NormapTex;
sampler2D DetailTex;
sampler2D SpecularTex;
sampler2D EmissionTex;




half4 detail_transform;
half environment_scale;
half4 emission_color;
half emission_scale;
half lightmap_scale;
half4 diffuse_color;
half4 specular_color;

half4 MaterialProperty;		// x: AlphaTest Ref Value.


struct VCommonV2F 
{
	float4 HPos : POSITION;
	float4 TexCoord : TEXCOORD0;
#if HAS_TANGENTSPACE
	half3 Tangent : TEXCOORD1;			// world to tangent basis
	half3 Binormal : TEXCOORD2;
	half3 Normal : TEXCOORD3;
#else 
	half3 Normal:TEXCOORD1;
#endif 

#ifdef AMBIENT_LIGHT
	float4 texcoord_4 : TEXCOORD4;
#ifdef SHADOW && USE_TRANSLUCENT
	float4 texcoord_5 : TEXCOORD5;
#endif
#endif
#ifdef PAINT
	float3 texcoord_4 : TEXCOORD4;
#endif
#ifdef FLECK
	float3 texcoord_6 : TEXCOORD6;
#endif
#ifdef TRIPLANAR || OVERLAP
	float4 texcoord_6 : TEXCOORD6;
#endif
#ifdef PATCH
	float2 texcoord_6 : TEXCOORD6;
#endif
#ifdef USE_DEFERRED || USE_OCCLUSION || (USE_PARALLAX && PARALLAX) || (USE_ALPHA_FADE && ALPHA_FADE)
	float4 texcoord_7 : TEXCOORD7;
#endif
};


struct VPixelContext
{
	float4 TexCoord;
	half4 Diffuse;		// diffuse color
	half3 Normal;		// tangent space or object Space Normal.
	half4 Specular;

#if HAS_TANGENTSPACE
	float3x3 TangentToWorld;
#endif 
};

half MGetAlpha(VPixelContext pCtx)
{
	return pCtx.Diffuse.w;
}

half4 MGetSpecular(VPixelContext pCtx)
{
	return pCtx.Specular;
}



#if VPASS_AMBIENT
VPixelContext VInitPixelContext(VCommonV2F Input)
{
	VPixelContext pCtx;
	pCtx.TexCoord = Input.TexCoord;
	pCtx.Diffuse = tex2D(DiffuseTex, pCtx.TexCoord.xy);
#if VALPHA_TEST
	if (pCtx.Diffuse.w < MaterialProperty.x)
	{
		discard;
	}
#endif 

	pCtx.Specular = tex2D(SpecularTex, pCtx.TexCoord.xy);
#if HAS_TANGENTSPACE
	pCtx.Normal = tex2D(NormapTex, pCtx.TexCoord.xy).xyz;
	pCtx.Normal = pCtx.Normal * 2.0f - 1.0f;
	pCtx.TangentToWorld = float3x3(Input.Tangent,Input.Binormal,Input.Normal);
#else
	pCtx.Normal = Input.Normal;
#endif 
	return pCtx;
}

half4 VAmbientPixel(VCommonV2F Input)
{
	VPixelContext pCtx = VInitPixelContext(Input);

	// something can move to ambient pixel shader.
#ifdef USE_OCCLUSION && !TRANSPARENT
	half deferred_ambient = tex2Dproj(s_texture_13,IN.texcoord_7).x;
	half3 ambient_color = s_ambient_color.xyz * deferred_ambient;
#else
	half3 ambient_color = s_ambient_color.xyz;
#endif

#if TRANSPARENT
	half3 color = pCtx.Diffuse.xyz;
#elif LIGHTMAP
	half3 lightmap = tex2DLightMap(s_texture_14,texcoord.zw,normal);
	half3 color = diffuse.xyz * (ambient_color + lightmap * lightmap_scale);
#else
	half3 color = pCtx.Diffuse.xyz /** ambient_color*/;
#endif

#ifdef EMISSION
	half3 emission = tex2D(s_texture_11,texcoord.xy).xyz;
	color += emission * emission_color.xyz * emission_scale;
#endif

#ifdef USE_ENVIRONMENT && !TRANSPARENT
	half3 world_normal = normalize(IN.texcoord_1 * normal.x + IN.texcoord_2 * normal.y + IN.texcoord_3 * normal.z);
	half3 environment = getEnvironment(world_normal);
	half ambient = tex2DCubic(s_texture_12,texcoord.zw,s_material_textures[12]).x;
#ifdef USE_OCCLUSION
	ambient *= deferred_ambient;
#endif
	color += diffuse.xyz * environment * (ambient * environment_scale);
#endif

#ifdef USE_DEFERRED && !TRANSPARENT
	half4 deferred_light = tex2Dproj(s_texture_15,IN.texcoord_7);
	color += getDiffuseSpecularDeferredAmbient(s_material_deferred,diffuse.xyz,specular.xyz,deferred_light);
#endif
	
	return half4(color,pCtx.Diffuse.w);
}
#elif VPASS_ZPASS
// init zpass pixel context
VPixelContext VInitPixelContextZPass(ZPassV2F Input)
{
	VPixelContext pCtx;

	pCtx.TexCoord = Input.TexCoord;

#if VALPHA_TEST
	pCtx.Diffuse = tex2D(DiffuseTex, pCtx.TexCoord.xy);
	if (pCtx.Diffuse.w < MaterialProperty.x)
	{
		discard;
	}
#endif 


#ifdef USE_ALPHA_FADE && ALPHA_FADE
	tex2DAlphaFadeDiscard(s_texture_9,IN.texcoord_7,IN.texcoord_7.z);
#endif
	

#ifdef USE_PARALLAX && PARALLAX
	half4 deferred_parallax = tex2Dproj(s_texture_10,IN.texcoord_7);
	texcoord.xy += getDeferredParallax(deferred_parallax);
#endif
	pCtx.Diffuse = tex2DAlpha(DiffuseTex,pCtx.TexCoord.xy,1.0f);

	
	pCtx.Specular = tex2D(SpecularTex, pCtx.TexCoord.xy);


#if HAS_TANGENTSPACE
	pCtx.Normal = tex2D(NormapTex, pCtx.TexCoord.xy).xyz;
	pCtx.TangentToWorld = float3x3(Input.Tangent,Input.Binormal,Input.Normal);
#else
	pCtx.Normal = Input.Normal;
#endif 



#ifdef OVERLAY_0 || OVERLAY_1 || MULTIPLY_0 || MULTIPLY_1

#ifdef OVERLAY_0 || MULTIPLY_0
	float2 detail_texcoord = texcoord.xy * detail_transform.xy + detail_transform.zw;
#else
	float2 detail_texcoord = texcoord.zw * detail_transform.xy + detail_transform.zw;
#endif

	half4 detail_diffuse = tex2D(s_texture_3,detail_texcoord);
	half2 detail_normal = tex2D(s_texture_4,detail_texcoord).xy;
	half3 detail_specular = tex2D(s_texture_5,detail_texcoord).xyz;

#ifdef ALPHA_TEST
	half3 blend = s_material_detail * detail_diffuse.w;
#else
	half3 blend = s_material_detail * (diffuse.w * detail_diffuse.w);
#endif

#ifdef OVERLAY_0 || OVERLAY_1
	diffuse.xyz = saturate(diffuse.xyz + (detail_diffuse.xyz * 2.0f - 1.0f) * blend.x);
	specular.xyz = saturate(specular.xyz + (detail_specular.xyz * 2.0f - 1.0f) * blend.z);
#else
	diffuse.xyz = diffuse.xyz * saturate(detail_diffuse.xyz + 1.0f - blend.x);
	specular.xyz = specular.xyz * saturate(detail_specular.xyz + 1.0f - blend.z);
#endif
	normal.xy = normal.xy + detail_normal * blend.y;

	normal.xy = normal.xy * 2.0f - 1.0f - blend.y;

#else
	//pCtx.Normal = pCtx.Normal * 2.0f - 1.0f;
#endif
	return pCtx;
}
#elif VPASS_SHADOWGEN

#endif 

half3 VPixelGetWorldNormal(VPixelContext pCtx)
{
#if HAS_TANGENTSPACE
	return mul(pCtx.TangentToWorld, pCtx.Normal);
#else 
	return pCtx.Normal;
#endif 
}

half PixelGetDepth(VPixelContext pCtx)
{
	return 0.h;
}

#if VPASS_DEPTHONLY



#elif VPASS_AMBIENT


#endif 